package com.cea.papyrus.multidiagram.extension;

import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.InvalidRegistryObjectException;
import org.eclipse.core.runtime.Platform;
import org.osgi.framework.Bundle;

/**
 * A factory used to create descriptor object from Eclipse extensions points elements.
 * TODO Rename to EditorDescriptorExtensionFactory
 */
public class ExtensionPointFactory {
 
	/** singleton  eINSTANCE of this class */
    public final static ExtensionPointFactory eINSTANCE = new ExtensionPointFactory();
    
    /**
     * @return the eINSTANCE
     */
    public static ExtensionPointFactory getInstance() {
        return eINSTANCE;
    }

    /**
     * Create a descriptor eINSTANCE corresponding to the ConfigurationElement.
     * @param element
     * @return
     * @throws BadNameExtensionException 
     */
    public NestedEditorDescriptor createNestedEditorDescriptor(IConfigurationElement element) throws ExtensionException {
        NestedEditorDescriptor res;
        String tagName = "editor";
        
        checkTagName(element, tagName);
        
        res = new NestedEditorDescriptor();
        res.setEditorFactoryClass(parseClass(element, "factoryClass") );
        
        for( IConfigurationElement ele : element.getChildren() ) {
            ActionBarButtonDescriptor button = createActionBarButtonDescriptor(ele);
            res.setCreateButtonDescriptor(button);
        }
        return res;
    }

    /**
     * Create a descriptor eINSTANCE corresponding to the ConfigurationElement.
     * @param element
     * @return
     */
    public ActionBarButtonDescriptor createActionBarButtonDescriptor(IConfigurationElement element) throws ExtensionException {
        ActionBarButtonDescriptor res;
        String tagName = "createEditorButton";
        checkTagName(element, tagName);
        
        res = new ActionBarButtonDescriptor();
        res.setPluginID(element.getDeclaringExtension().getNamespaceIdentifier());
        res.setCreateEditorActionClass(parseClass(element, "action") );
        res.setActionID(element.getAttribute("actionId"));
        res.setCreateDiagramLabel(element.getAttribute("label"));
        res.setCreateDiagramTooltip(element.getAttribute("tooltip"));
        
        res.setCreateDiagramImage(element.getAttribute("image"));
        res.setCreateDiagramDisableImage(element.getAttribute("disabledImage"));
        return res;
    }

    
    /**
     * @param element
     * @param tagName
     * @throws InvalidRegistryObjectException
     * @throws BadNameExtensionException
     */
    private void checkTagName(IConfigurationElement element, String tagName) throws BadNameExtensionException {
        String name = element.getName();
        if( ! tagName.equals(name) )
            throw new BadNameExtensionException("Expected '" + tagName + "', found '" + name + "'.");
    }

    /**
     * Retrieves the value of a specific attribute in a configuration element
     * @param element the configuration element to parse
     * @param attributeName the name of the attribute to read
     * @return the class, result of the parsing
     * @throws InvalidRegistryObjectException
     * @throws BadClassNameException
     */
    private Class parseClass(IConfigurationElement element, String attributeName) throws BadClassNameException  {    	
        String className = element.getAttribute(attributeName);
        Class factoryClass;
        try {
        	factoryClass = Class.forName(className);
         } catch (ClassNotFoundException e) {
        	 // try another way
        	 try {
        	   String declaringID = element.getContributor().getName();
        	   Bundle bundle = Platform.getBundle(declaringID);
			   factoryClass = bundle.loadClass(className);
			} catch (ClassNotFoundException e1) {
				throw new BadClassNameException(element, attributeName, e1);
			}
        }
        return factoryClass;
    }
 }
